package com.cofi.vueelementadminserver.config.security;

import com.cofi.vueelementadminserver.config.security.jwt.JwtRequestFilter;
import com.cofi.vueelementadminserver.service.StmUserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.ProviderManager;
import org.springframework.security.authentication.dao.DaoAuthenticationProvider;
import org.springframework.security.config.Customizer;
import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityCustomizer;
import org.springframework.security.config.annotation.web.configurers.AbstractHttpConfigurer;
import org.springframework.security.crypto.bcrypt.BCrypt;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.web.SecurityFilterChain;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;

/**
 * @author xyh
 * @date 2024-11-29
 * @description spring security 相关配置
 */
@Configuration
@EnableWebSecurity
@EnableGlobalMethodSecurity(prePostEnabled = true)
public class SecurityConfig {

    @Autowired
    public StmUserService userService;

    @Autowired
    public SecurityUserDetailsService userDetailsService;

    @Autowired
    private JwtRequestFilter jwtRequestFilter;


    public static void main(String[] args) {
        String noopPwd = "111111";
        BCryptPasswordEncoder bCryptPasswordEncoder = new BCryptPasswordEncoder();
        String salt = BCrypt.gensalt();
        System.out.println("salt: " + salt);
        String pwd = bCryptPasswordEncoder.encode(noopPwd);
        System.out.println(pwd);

        String customPassword = BCrypt.hashpw(noopPwd, salt);
        System.out.println("customPassword:" + customPassword);

        boolean matches = bCryptPasswordEncoder.matches(noopPwd, customPassword);
        System.out.println("matches:" + matches);
    }

    //密码加密方式
    @Bean
    public PasswordEncoder passwordEncoder() {
        return new BCryptPasswordEncoder();
    }

    //内存形式的用户信息
//    @Bean
//    UserDetailsService userDetailsService(){
//        InMemoryUserDetailsManager inMemoryUserDetailsManager = new InMemoryUserDetailsManager();
//        inMemoryUserDetailsManager.createUser(
//                User.builder()
//                        .username("admin")
////                        .password("{noop}111111")
//                        .password("$2a$10$l8Ump4znfOK6z62Ph96Z3ehnBE/BfK4OVdPevoM7Y/jF/GAdKtc6i")
//                        .roles("ADMIN","SSSS").build()
//        );
//        return inMemoryUserDetailsManager;
//    }

    //认证最底层管理器
    @Bean
    AuthenticationManager authenticationManager(){
        DaoAuthenticationProvider daoAuthenticationProvider = new DaoAuthenticationProvider();
        daoAuthenticationProvider.setUserDetailsService(userDetailsService);
        daoAuthenticationProvider.setPasswordEncoder(passwordEncoder());
        return new ProviderManager(daoAuthenticationProvider);
    }

    //自定义拦截器，用于前后端分离
    @Bean
    public SplitLoginFilter splitLoginFilter(){
        SplitLoginFilter splitLoginFilter = new SplitLoginFilter();
        splitLoginFilter.setAuthenticationManager(authenticationManager());
        splitLoginFilter.setAuthenticationSuccessHandler(new MyLoginSuccessHandler());
        splitLoginFilter.setAuthenticationFailureHandler(new MyLoginFailHandler());
        return splitLoginFilter;
    }

    /**
     * 代替原configure
     *
     * @param http HttpSecurity 实例
     * @return security过滤链
     * @throws Exception 异常信息
     */
    @Bean
    public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
        http.authorizeHttpRequests(
                auth -> {
                    //除login请求外，全部身份验证
                    auth.requestMatchers("/login").permitAll()
                            .requestMatchers("/test").permitAll()
                            .requestMatchers("/user/info").permitAll()
                            .anyRequest().authenticated();

                })
                .formLogin(
                        //设置登录相关参数
                        fl -> fl.usernameParameter("username")
                        .passwordParameter("password")
                        .successHandler(new MyLoginSuccessHandler()) //登录成功处理器
                        .failureHandler(new MyLoginFailHandler()) //登录失败处理器
                )
                .userDetailsService(userDetailsService)
                .httpBasic(Customizer.withDefaults());


        http.addFilterAt(splitLoginFilter(), UsernamePasswordAuthenticationFilter.class);
        http.addFilterAfter(jwtRequestFilter, UsernamePasswordAuthenticationFilter.class);
        //跨站请求伪造（CSRF）攻击及防御
        http.csrf(AbstractHttpConfigurer::disable);
        return http.build();
    }

    @Bean
    public WebSecurityCustomizer webSecurityCustomizer() {
        return webSecurity -> {
            webSecurity.ignoring()
                    .requestMatchers(
                            "/js/**",
                            "/css/**",
                            "/images/**",
                            "/fonts/**");
        };
    }
}
